package com.hbasesoft.hamibot.config;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.alibaba.fastjson2.JSONObject;
import com.hbasesoft.framework.common.GlobalConstants;
import com.hbasesoft.framework.common.utils.PropertyHolder;
import com.hbasesoft.framework.common.utils.logger.LoggerUtil;
import com.hbasesoft.framework.common.utils.security.DESUtil;
import com.hbasesoft.framework.common.utils.security.DataUtil;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;

/**
 * <Description> <br>
 * 
 * @author 王伟<br>
 * @version 1.0<br>
 * @taskId <br>
 * @CreateDate 2020年12月4日 <br>
 * @since V1.0<br>
 * @see com.hbasesoft.cloud.common.ui <br>
 */
@Configuration
public class UIWebConfig implements WebMvcConfigurer {

    /**
     *
     */
    private static final String STATIC_PATH = PropertyHolder.getProperty("server.servlet.staticPath", "static");

    /**
     *
     */
    private static final String[] SUFFIXES = StringUtils.split(PropertyHolder.getProperty("server.ui.suffix",
        "*.js,*.css,*.ttf,*.otf,*.eot,woff,woff2,*.swf,*.svg,*.jpg,*.jpge,*.png,*.gif,*.ico,*.txt,*.pdf,*.html,*.json"),
        GlobalConstants.SPLITOR);

    /**
     * Description: <br>
     * 
     * @author 王伟<br>
     * @taskId <br>
     * @param registry <br>
     */
    @Override
    public void addInterceptors(final InterceptorRegistry registry) {

        final Map<String, String> htmlConfig = new HashMap<>();
        String htmlConfigValue = PropertyHolder.getProperty("frontendHtml");
        if (StringUtils.isNotEmpty(htmlConfigValue)) {
            String[] hs = StringUtils.split(htmlConfigValue);
            for (String h : hs) {
                String[] hc = StringUtils.split(h, "=");
                if (hc != null && hc.length == 2) {
                    htmlConfig.put(StringUtils.trim(hc[0]), StringUtils.trim(hc[1]));
                }
            }
        }

        List<String> pathPatterns = new ArrayList<>();
        List<String> excloudePathPatterns = new ArrayList<>();

        UIConfig config = new UIConfig();
        config.setContextPath("/task-app");
        config.setIndexFilename("index.html");

        String indexFile = new StringBuilder().append(STATIC_PATH).append(config.getContextPath()).append('/')
            .append(config.getIndexFilename()).toString();
        String indexHtml = null;
        try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(indexFile)) {
            indexHtml = IOUtils.toString(in, GlobalConstants.DEFAULT_CHARSET);
            if (MapUtils.isNotEmpty(htmlConfig)) {
                for (Entry<String, String> entry : htmlConfig.entrySet()) {
                    indexHtml = StringUtils.replace(indexHtml, entry.getKey(), entry.getValue());
                }
            }
        }
        catch (Exception e) {
            LoggerUtil.error(e);
        }
        pathPatterns.add(config.getContextPath());
        pathPatterns.add(config.getContextPath() + "/**");
        pathPatterns.add(config.getContextPath() + '/' + config.getIndexFilename());

        for (String suffix : SUFFIXES) {
            excloudePathPatterns.add(config.getContextPath() + "/**/" + suffix);
        }

        registry.addInterceptor(new HtmlInterceptor(indexHtml)).addPathPatterns(pathPatterns)
            .excludePathPatterns(excloudePathPatterns);

        LoggerUtil.info("加载UI模块成功，{0}, pathPaggerns={1}, excludePathPatterns={2}", config.getContextPath(),
            pathPatterns, excloudePathPatterns);

    }

    @RequiredArgsConstructor
    private static final class HtmlInterceptor implements HandlerInterceptor {

        /** html页面缓存 */
        private final String cacheContent;

        @Override
        public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response,
            final Object handler) throws Exception {

            if (request.getRequestURI().endsWith("/frontend.cfg")) {
                response.setContentType("text/plain");
                response.setCharacterEncoding(GlobalConstants.DEFAULT_CHARSET.displayName());
                response.getOutputStream().print(readFrontCfg());
                response.getOutputStream().flush();
                return false;
            }

            response.setCharacterEncoding(GlobalConstants.DEFAULT_CHARSET.displayName());
            response.setContentType("text/html");
            response.getWriter().print(cacheContent);
            return false;
        }
    }

    private static String readFrontCfg() {
        final String prefix = "frontend.";
        final int size = prefix.length();
        Map<String, String> props = PropertyHolder.getProperties();
        JSONObject obj = new JSONObject();
        for (Entry<String, String> entry : props.entrySet()) {
            String key = entry.getKey();
            if (key.startsWith(prefix)) {
                obj.put(key.substring(size), PropertyHolder.getProperty(key));
            }
        }
        String clientId = PropertyHolder.getProperty("server.client_id");
        String clientSecret = PropertyHolder.getProperty("server.client_secret");
        if (StringUtils.isNotEmpty(clientId) && StringUtils.isNotEmpty(clientSecret)) {
            long time = System.currentTimeMillis();
            String sgin = DataUtil
                .md5(new StringBuilder().append(clientId).append(time).append(clientSecret).toString());
            obj.put("client_secret", new StringBuilder().append(time).append('.').append(sgin).toString());
        }
        return DESUtil.encryption(obj.toJSONString());
    }
}
